package com.probiz.estore.product.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import com.probiz.estore.Constants;
import com.probiz.estore.common.model.catalog.ProductCategory;
import com.probiz.estore.common.model.inventory.Inventory;
import com.probiz.estore.common.model.product.Product;
import com.probiz.estore.common.model.product.ProductSku;
import com.probiz.estore.common.model.product.ProductSkuOptionValue;
import com.probiz.estore.common.model.product.ProductType;
import com.probiz.estore.common.model.product.SkuOption;
import com.probiz.estore.common.model.product.SkuOptionValue;
import com.probiz.estore.common.model.product.WholesalePrice;
import com.probiz.estore.core.service.impl.GenericManagerImpl;
import com.probiz.estore.core.util.I18nUtil;
import com.probiz.estore.inventory.dao.InventoryDao;
import com.probiz.estore.product.dao.ProductSkuDao;
import com.probiz.estore.product.service.ProductSkuManager;
import com.probiz.estore.product.util.ProdCodeGenerator;


/**
 * Manager implementation for ProductSku, responsible for business processing, and communicate between web and persistence layer.
 */
public class ProductSkuManagerImpl extends GenericManagerImpl<ProductSku> implements ProductSkuManager {

	private ProductSkuDao productSkuDao = null;
	private InventoryDao inventoryDao = null;

	/**
	 * @param productSkuDao
	 *            the productSkuDao to set
	 */
	public void setProductSkuDao(ProductSkuDao productSkuDao) {
		this.productSkuDao = productSkuDao;
	}

	public void setInventoryDao(InventoryDao inventoryDao) {
		this.inventoryDao = inventoryDao;
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see com.probiz.estore.core.service.impl.GenericManagerImpl#init()
	 */
	@Override
	protected void initManager() {
		dao = productSkuDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.probiz.estore.core.service.impl.GenericManagerImpl#onDelete(java.lang.Object)
	 */
	@Override
	protected void preDelete(ProductSku entity) {

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.probiz.estore.core.service.impl.GenericManagerImpl#onSave(java.lang.Object)
	 */
	@Override
	protected void preSave(ProductSku entity) {

	}
	
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.product.service.ProductSkuManager#saveSkusFromArrays(com.probiz.estore.product.model.Product, java.lang.String[], java.lang.String[], java.lang.String[])
	 */
	public List<String> saveSkusFromArrays(Product product, Map<String, Object>  returnMsgs, String[] skuIds, String[] skuCodes,
			String[] skuImageUrls,String[] listPrices,String[] prices,String[] salePrices,String[] weights,String[] skuOptionValueInfos){
		List<String> newSkuIdList = new ArrayList<String>();
		//删除SKU
		List<String> skuIdList=Arrays.asList(skuIds);
		Set<ProductSku> formerSkuList=product.getProductSkus();//原来的SKUs
		for (ProductSku sku : formerSkuList) {
			if(!skuIdList.contains(sku.getProductSkuId().toString())){
				
				deleteFully(sku);
				
			}
		}
		//增加或者修改SKU
		for (int i = 0; i < skuIds.length; i++) {
			ProductSku sku ;
			
			
			if(skuIds[i].equals("")){
				//case:新增
				sku = new ProductSku();
			}else{
				//case:修改
				sku = getById(Integer.valueOf(skuIds[i]));
			}
			
			//start:设置货品编码并检查
			if(StringUtils.isBlank(skuCodes[i])){
				boolean isCodeAvailable = false;
				do{
					String productSkuCode = ProdCodeGenerator.generateProductSkuCode();
					Integer skuId = skuIds[i].equals("")?null:(Integer.parseInt(skuIds[i]));
					Long size = productSkuDao.getSizeByProductSkuCodeByNotProductSkuId(productSkuCode, skuId);
					if(size==0){
						//该货品编码可用
						isCodeAvailable = true;
						sku.setProductSkuCode(productSkuCode);
					}
				}while(!isCodeAvailable);
			}else{
				//用getSizeByProductSkuCodeByNotProductSkuId而不用getProductSkuByProductSkuCode的原因在于调用后者的时候会有update操作，造成数据库有两个相同code的单品，出错
				Integer skuId = skuIds[i].equals("")?null:(Integer.parseInt(skuIds[i]));
				Long size = productSkuDao.getSizeByProductSkuCodeByNotProductSkuId(skuCodes[i], skuId);
				
				if(size>=1){
					//货品编码重复
					returnMsgs.put("error", I18nUtil.getInstance().getMessage("productSku.productSkuCode.repeated",new Object[]{skuCodes[i]}));
					return null;
					
				}else{
					sku.setProductSkuCode(skuCodes[i]); //设置货品编码
				}
			}
			
			skuCodes[i] = sku.getProductSkuCode(); //设置返回参数，页面重新显示
			//end:设置单品编码并检查
			
			sku.setImageUrl(skuImageUrls[i]);
			
			if(StringUtils.isNotBlank(listPrices[i])){
				sku.setListPrice(new BigDecimal(listPrices[i]));
			}else{
				sku.setListPrice(null);
			}
			if(StringUtils.isNotBlank(prices[i])){
				sku.setPrice(new BigDecimal(prices[i]));
			}else{
				sku.setPrice(null);
			}
			if(StringUtils.isNotBlank(salePrices[i])){
				sku.setSalePrice(new BigDecimal(salePrices[i]));
			}else{
				sku.setSalePrice(null);
			}
			if(StringUtils.isNotBlank(weights[i])){
				sku.setWeight(new BigDecimal(weights[i]));
			}else{
				sku.setWeight(null);
			}	
			sku.setSkuOptionValueInfo(skuOptionValueInfos[i]);
			sku.setSortOrder(i);
			sku.setStatus(Constants.FLAG_TRUE);
			sku.setProduct(product);
			save(sku);
			newSkuIdList.add(sku.getProductSkuId().toString());
		}
		return newSkuIdList;
	}
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.product.service.ProductSkuManager#savePricesFromArrays(java.util.Map, java.lang.String[], java.lang.String[], java.lang.String[], java.lang.String[], java.lang.String[])
	 */
	public List<String> savePricesFromArrays(Map<String, Object>  returnMsgs, String[] skuIds, String[] listPrices,String[] prices,String[] salePrices,String[] weights){
		List<String> newSkuIdList = new ArrayList<String>();
		for (int i = 0; i < skuIds.length; i++) {
			ProductSku sku = getById(Integer.valueOf(skuIds[i]));
			
			if(StringUtils.isNotBlank(listPrices[i])){
				sku.setListPrice(new BigDecimal(listPrices[i]));
			}else{
				sku.setListPrice(null);
			}
			if(StringUtils.isNotBlank(prices[i])){
				sku.setPrice(new BigDecimal(prices[i]));
			}else{
				sku.setPrice(null);
			}
			if(StringUtils.isNotBlank(salePrices[i])){
				sku.setSalePrice(new BigDecimal(salePrices[i]));
			}else{
				sku.setSalePrice(null);
			}
			if(StringUtils.isNotBlank(weights[i])){
				sku.setWeight(new BigDecimal(weights[i]));
			}else{
				sku.setWeight(null);
			}	
			sku.setSortOrder(i);
			sku.setStatus(Constants.FLAG_TRUE);
			save(sku);
			newSkuIdList.add(sku.getProductSkuId().toString());
		}
		return newSkuIdList;
		
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.product.service.ProductSkuManager#getSkuOptionValueInfos(java.util.Map, java.lang.String[], java.lang.String[], java.util.List)
	 */
	public String[] getSkuOptionValueInfos(Map<String, Object>  returnMsgs ,String[] skuIds, String[] optionIds,List<String[]> skuOptionValueIdsList){
		//先生成
		List<String> skuOptionValueInfoList = new ArrayList<String>();
		for(int i=0; i< skuIds.length; i++){
			List<String> relationOptionValueIds = new ArrayList<String>(); //存放sku对应的规格值id
			for(String[] skuOptionValueIds: skuOptionValueIdsList){
				relationOptionValueIds.add(skuOptionValueIds[i]);
			}
			
			StringBuffer sb = new StringBuffer();
			for(int j=0; j< optionIds.length; j++){
				sb.append(optionIds[j]).append(":").append(relationOptionValueIds.get(j)).append(";");
			}	
			skuOptionValueInfoList.add(sb.toString());
		
		}
		//后检查有没有重复
		outer:for(int i=0; i<skuOptionValueInfoList.size(); i++){
			String info = skuOptionValueInfoList.get(i);
			for(int j=i+1; j<skuOptionValueInfoList.size();j++){
				if(StringUtils.isNotBlank(info) && info.equals(skuOptionValueInfoList.get(j))){
					//有重复
					returnMsgs.put("error", I18nUtil.getInstance().getMessage("productSku.existSameOptionValues"));
					break outer;
				}
			}
		}
		return skuOptionValueInfoList.toArray(new String[0]);
		
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.product.service.ProductSkuManager#getProductSkuByProductSkuCode(java.lang.String)
	 */
	public ProductSku getProductSkuByProductSkuCode(String productSkuCode){
		return productSkuDao.getUniqueByProperty("productSkuCode", productSkuCode);
	}
	/**
	 * 非常重要，必须把所有关联都设置好
	 */
	public ProductSku getProductSkuPojoByProductSkuCode(String productSkuCode){
		try {
			ProductSku productSku = productSkuDao.getUniqueByProperty("productSkuCode", productSkuCode);
			if (productSku != null) {
				ProductSku result = new ProductSku();
				result.setProductSkuId(productSku.getProductSkuId());
				result.setProductSkuCode(productSku.getProductSkuCode());
				result.setDiscountPrice(productSku.getDiscountPrice());
				result.setListPrice(productSku.getListPrice());
				result.setWeight(productSku.getWeight());
				result.setHeight(productSku.getHeight());
				result.setSalePrice(productSku.getSalePrice());
				result.setPrice(productSku.getPrice());
				result.setDiscountPrice(productSku.getDiscountPrice());
				result.setSkuOptionValueInfo(productSku.getSkuOptionValueInfo());
				result.setHasDiscount(productSku.isHasDiscount());
				result.setStatus(productSku.getStatus());
				result.setVersion(productSku.getVersion());
				
				Set<ProductSkuOptionValue> tmpProductSkuOptionValues = new HashSet<ProductSkuOptionValue>();
				if (productSku.getProductSkuOptionValues() != null) {
					for(ProductSkuOptionValue pso: productSku.getProductSkuOptionValues()){
						ProductSkuOptionValue tmpProductSkuOptionValue = new ProductSkuOptionValue();
						SkuOptionValue tmpSkuOptionValue = new SkuOptionValue();
						SkuOption tmpSkuOption = new SkuOption();
						tmpSkuOption.setSkuOptionName(pso.getSkuOptionValue().getSkuOption().getSkuOptionName());
						tmpSkuOptionValue.setSkuOption(tmpSkuOption);
						tmpSkuOptionValue.setSkuOptionValueName(pso.getSkuOptionValue().getSkuOptionValueName());
						tmpProductSkuOptionValue.setProductSkuOptionValueId(pso.getProductSkuOptionValueId());
						tmpProductSkuOptionValue.setSkuOptionValue(tmpSkuOptionValue);
						tmpProductSkuOptionValues.add(tmpProductSkuOptionValue);
					}
				}
				result.setProductSkuOptionValues(tmpProductSkuOptionValues);
				
				if(productSku.getWholesalePrices() != null){
					Set<WholesalePrice> tmpWholesalePrices = new HashSet<WholesalePrice>();
					for(WholesalePrice wholesalePrice: productSku.getWholesalePrices()){
						WholesalePrice tmpWholesalePrice = new WholesalePrice();
						tmpWholesalePrice.setMinQuantity(wholesalePrice.getMinQuantity());
						tmpWholesalePrice.setMaxQuantity(wholesalePrice.getMaxQuantity());
						tmpWholesalePrice.setPrice(wholesalePrice.getPrice());
						tmpWholesalePrice.setSortOrder(wholesalePrice.getSortOrder());
						tmpWholesalePrice.setProductSku(productSku);
						tmpWholesalePrices.add(tmpWholesalePrice);
					}
					result.setWholesalePrices(tmpWholesalePrices);
				}
				
				if (productSku.getInventory() != null) {
					Inventory tmpInventroy = new Inventory();
					tmpInventroy.setInventoryId(productSku.getInventory().getInventoryId());
					tmpInventroy.setAllocatedQuantity(productSku.getInventory().getAllocatedQuantity());
					tmpInventroy.setReorderMinimnm(productSku.getInventory().getReorderMinimnm());
					tmpInventroy.setQuantityOnHand(productSku.getInventory().getQuantityOnHand());
					tmpInventroy.setCreateTime(productSku.getInventory().getCreateTime());
					tmpInventroy.setVersion(productSku.getInventory().getVersion());
					result.setInventory(tmpInventroy);
					inventoryDao.evict(productSku.getInventory());
				}
				
				if (productSku.getProduct() != null) {
					Product tmpProduct = new Product();
					tmpProduct.setProductId(productSku.getProduct().getProductId());
					tmpProduct.setProductName(productSku.getProduct().getProductName());
					tmpProduct.setProductKind(productSku.getProduct().getProductKind());
					tmpProduct.setCategoryId(productSku.getProduct().getCategoryId());
					tmpProduct.setDefaultProductSku(result);
					tmpProduct.setDefaultProductSkuId(result.getProductSkuId());
					tmpProduct.setImageUrl(productSku.getProduct().getImageUrl());
					tmpProduct.setMaxOrderQuantity(productSku.getProduct().getMaxOrderQuantity());
					tmpProduct.setMinOrderQuantity(productSku.getProduct().getMinOrderQuantity());
					tmpProduct.setPrice(productSku.getProduct().getPrice());
					tmpProduct.setProductCode(productSku.getProduct().getProductCode());
					tmpProduct.setWeightMeasureUnitName(productSku.getProduct().getWeightMeasureUnitName());
					tmpProduct.setBrand(productSku.getProduct().getBrand());
					
					if (productSku.getProduct().getProductType() != null) {
						ProductType tmpProductType = new ProductType();
						tmpProductType.setKind(productSku.getProduct().getProductType().getKind());
						tmpProductType.setProductTypeId(productSku.getProduct().getProductType().getProductTypeId());
						tmpProduct.setProductType(tmpProductType);
						
					}
					if (productSku.getProduct().getCategory() != null) {
						ProductCategory tmpProductCategory = new ProductCategory();
						tmpProductCategory.setCategoryCode(productSku.getProduct().getCategory().getCategoryCode());
						tmpProductCategory.setCategoryName(productSku.getProduct().getCategory().getCategoryName());
						tmpProductCategory.setCategoryId(productSku.getProduct().getCategory().getCategoryId());
						tmpProductCategory.setCategoryPath(productSku.getProduct().getCategory().getCategoryPath());
						tmpProductCategory.setImageUrl(productSku.getProduct().getCategory().getImageUrl());
						tmpProduct.setCategory(tmpProductCategory);
					}
					
					result.setProduct(tmpProduct);
				}
				return result;
			}
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.product.service.ProductSkuManager#getSizeByProductSkuCodeByNotProductSkuId(java.lang.String, java.lang.Integer)
	 */
    public Long getSizeByProductSkuCodeByNotProductSkuId(String productSkuCode,Integer productSkuId){
    	return productSkuDao.getSizeByProductSkuCodeByNotProductSkuId(productSkuCode, productSkuId);
    }
    /*
     * (non-Javadoc)
     * @see com.probiz.estore.product.service.ProductSkuManager#deleteFully(com.probiz.estore.common.model.product.ProductSku)
     */
    public void deleteFully(ProductSku sku){
    	if(null != sku.getInventory())inventoryDao.delete(sku.getInventory());
    	productSkuDao.delete(sku);
    }
}
